package com.alibaba.citrus.cr.mn.order.center.facade.function.convert;

import com.alibaba.citrus.cr.common.constant.OrderFeaturesKey;
import com.alibaba.citrus.cr.common.enums.ordercenter.FulfillmentStatusEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.OrderCategoryEnum;
import com.alibaba.citrus.cr.common.exception.FunctionException;
import com.alibaba.citrus.cr.common.util.DateUtils;
import com.alibaba.citrus.cr.mn.order.center.common.SetOrderTag;
import com.alibaba.citrus.cr.mn.order.center.common.util.MoneyUtils;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.BaseDataServiceAdapter;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.CargoZoneAdapter;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.dataobject.request.SearchScItemQueryRequest;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.dataobject.response.BaseDataScItemDTO;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcorder.model.dto.SpecQueryWarehouseRequest;
import com.epoch.app.bcorder.model.dto.WarehouseInfo;
import com.epoch.app.bcorder.model.dto.WmsQueryWarehouseZoneListRequest;
import com.epoch.app.bcorder.model.dto.WmsQueryWarehouseZoneListResponse;
import com.epoch.app.bcorder.service.BcOrderService;
import com.epoch.app.bcorder.service.UnifiedInventoryService;
import com.epoch.app.crb2btradecenter.domain.orderline.model.OrderLine;
import com.epoch.app.crb2btradecenter.enums.OrderStatus;
import com.epoch.app.mnordercenter.orderbaserequest.OrderLineAtomUpdateRequest;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zhangxiaorui
 * @ClassName OrderLineConvert
 * @description: TODO
 * @date 2023/05/17 15:27
 * @version: 1.0
 */
@Service
public class OrderLineAtomUpdateRequestToOrderLineConvert {

    private static final Logger log = LoggerFactory.getLogger(OrderLineAtomUpdateRequestToOrderLineConvert.class);

    @Resource
    private BaseDataServiceAdapter baseDataServiceAdapter;
    @Resource
    private BcOrderService bcOrderService;
    @Resource
    private UnifiedInventoryService unifiedInventoryService;
    @Resource
    private CargoZoneAdapter cargoZoneAdapter;

    public OrderLine convert(OrderLineAtomUpdateRequest lineRequest) {
        OrderLine lineSDO = new OrderLine();
        BeanUtils.copyProperties(lineRequest, lineSDO);
        log.info("lineRequest参数:{}",JSON.toJSONString(lineRequest));
        lineSDO.setScItemOutCode(lineRequest.getProductCode());
        lineSDO.setScItemTitle(lineRequest.getProductName());
        lineSDO.setQuantity(Integer.parseInt(lineRequest.getProductQuantity()));
        lineSDO.setSaleUnit(lineRequest.getSalesUnitCode());
        lineSDO.setSaleUnitName(lineRequest.getSalesUnitName());
        lineSDO.setInventoryUnitCode(lineRequest.getStockUnitCode());
        lineSDO.setInventoryUnit(lineRequest.getStockUnitName());
        lineSDO.setUnitPrice(MoneyUtils.moneyStrYuan2Fen(lineRequest.getUnitPrice()));
        lineSDO.setShouldPayFee(MoneyUtils.moneyStrYuan2Fen(lineRequest.getTotalAmount()));
        lineSDO.setUnitConvert(lineRequest.getUnitConversionRelationship());
        lineSDO.setProductationTime(DateUtils.string2Date(lineRequest.getProductionDate()));
        lineSDO.setRemark(lineRequest.getNote());
        lineSDO.setSourceLineNum(lineRequest.getSourceLineNum());
        lineSDO.setSubStatus(String.valueOf(OrderStatus.BEFORE_DELIVERY.getCode()));
        lineSDO.setBizFeatures(lineRequest.getBizFeatures());
        if (StringUtils.isNotBlank(lineSDO.getUnitConvert()) && Objects.nonNull(lineSDO.getQuantity())) {
            lineSDO.setStockConversionNum(new BigDecimal(lineSDO.getQuantity()).divide(new BigDecimal(lineSDO.getUnitConvert()), 2, RoundingMode.HALF_UP).toString());
        }
        if (StringUtils.isNotBlank(lineRequest.getConfirmQuantity())) {
            lineSDO.setConfirmQuantity(Integer.parseInt(lineRequest.getConfirmQuantity()));
        }

        Map<String, String> features = Maps.newHashMap();
        if (StringUtils.isNotBlank(lineRequest.getManualPrice())) {
            lineSDO.setManualPrice(lineRequest.getManualPrice());
            features.put(OrderFeaturesKey.MANUAL_PRICE, lineRequest.getManualPrice());//手工单价
        }
        if (StringUtils.isNotBlank(lineRequest.getManualTotalAmount())) {
            features.put(OrderFeaturesKey.MANUAL_TOTAL_AMOUNT, lineRequest.getManualTotalAmount());//手工总金额
            lineSDO.setManualTotalAmount(lineRequest.getManualTotalAmount());
        }
        if (StringUtils.isNotBlank(lineRequest.getSourcePrice())) {
            features.put(OrderFeaturesKey.SOURCE_PRICE, lineRequest.getSourcePrice());// 来单价格
        }
        if (StringUtils.isNotBlank(lineRequest.getSourceQuantity())) {
            features.put(OrderFeaturesKey.SOURCE_QUANTITY, lineRequest.getSourceQuantity());// 来单数量
        }
        if (StringUtils.isNotBlank(lineRequest.getSourceUnit())) {
            features.put(OrderFeaturesKey.SOURCE_UNIT, lineRequest.getSourceUnit());// 来单单位
        }
        if (StringUtils.isNotBlank(lineRequest.getInvoiceNo())) {
            features.put(OrderFeaturesKey.INVOICE_NO, lineRequest.getInvoiceNo());// 发票号
        }
        if (StringUtils.isNotBlank(lineRequest.getInvoiceLineNo())) {
            features.put(OrderFeaturesKey.INVOICE_LINE_NO, lineRequest.getInvoiceLineNo());// 发票行号
        }
        lineSDO.setFeatures(JSONObject.toJSONString(features));

        String scItemOutCode = lineRequest.getProductCode();
        Map<String, BaseDataScItemDTO> scItemDTOMap = queryScItemInfo(Arrays.asList(scItemOutCode));
        BaseDataScItemDTO scItem = scItemDTOMap.get(scItemOutCode);
        if (scItem == null) {
            throw new FunctionException("OC-01-001-01-16-012", scItemOutCode);
        }
        lineSDO.setScItemId(scItem.getScItemId());
        WarehouseInfo warehouseInfo = queryLgWarehouseInfo(lineSDO.getShippingWarehouseCode(), lineSDO.getDeliveryFactoryCode(), lineSDO.getStockCode());
        WarehouseInfo receiveWarehouseInfo = queryReceiveWarehouseInfo(lineSDO);
        if (receiveWarehouseInfo != null) {
            lineSDO.setReceiveStockCode(receiveWarehouseInfo.getWarehouseCode());
            lineSDO.setReceiveFactoryCode(receiveWarehouseInfo.getSapFactoryCode());
            lineSDO.setReceiveWarehouseName(receiveWarehouseInfo.getName());
            lineSDO.setReceiveWarehouseCode(receiveWarehouseInfo.getId());
            lineSDO.setReceiveWarehouseOutCode(receiveWarehouseInfo.getCode());
        }
        lineSDO.setShippingWarehouseCode(warehouseInfo.getId());
        lineSDO.setShippingWarehouseOutCode(warehouseInfo.getCode());
        lineSDO.setShippingWarehouseName(warehouseInfo.getName());
        if (StringUtils.isNotBlank(warehouseInfo.getWarehouseCode())) {
            lineSDO.setStockCode(warehouseInfo.getWarehouseCode());
        }
        lineSDO.setDeliveryFactoryCode(warehouseInfo.getSapFactoryCode());
        return lineSDO;
    }

    private Map<String, BaseDataScItemDTO> queryScItemInfo(List<String> scItemCodes) {
        if (CollectionUtils.isEmpty(scItemCodes)) {
            return Maps.newHashMap();
        }
        SearchScItemQueryRequest request = new SearchScItemQueryRequest();
        request.setPageNum(1);
        request.setPageSize(scItemCodes.size());

        Map<String, Object> searchReqDTO = Maps.newHashMap();
        searchReqDTO.put("outerIdList", scItemCodes);
        request.setSearchReqDTO(searchReqDTO);
        List<BaseDataScItemDTO> scItemDTOS = baseDataServiceAdapter.searchScItemByDBWhenDegraded(request);

        return Optional.ofNullable(scItemDTOS).orElse(Lists.newArrayList())
                .stream()
                .collect(Collectors.toMap(BaseDataScItemDTO::getOuterId, p -> p, (v1, v2) -> v1));
    }

    private WarehouseInfo queryReceiveWarehouseInfo(OrderLine orderLine) {
        if(SetOrderTag.EXCHANGE.equals(orderLine.getOrderLineTag())) {
            String shippingWarehouseCode = orderLine.getReceiveWarehouseCode();
            if (StringUtils.isBlank(shippingWarehouseCode)) {
                // 查看是否已经缓存 工厂+库存地点
                String key = String.format("%s_%s", orderLine.getDeliveryFactoryCode(), orderLine.getStockCode());
                // 当逻辑仓库信息为空时，通过 交货工厂编码+交货库存地点 填充
                SpecQueryWarehouseRequest cargoRequest = new SpecQueryWarehouseRequest();
                cargoRequest.setFactoryCode(orderLine.getReceiveFactoryCode());
                cargoRequest.setInventoryCode(orderLine.getReceiveStockCode());
                cargoRequest.setModel(3);
                //销售单元仓 TODO 3.6 啥意思
                cargoRequest.setTypeList(Lists.newArrayList(3, 6));
                Result<List<WarehouseInfo>> cargoResponse = bcOrderService.specQueryWarehouse(cargoRequest);
                if (Objects.isNull(cargoResponse) || CollectionUtils.isEmpty(cargoResponse.getResult())) {
                    throw new FunctionException("OC-01-001-01-16-009", String.format("工厂编码:%s, 库存地点编码:%s",
                            orderLine.getDeliveryFactoryCode(),
                            orderLine.getStockCode()));
                }
                WarehouseInfo queryWarehouseInfo = cargoResponse.getResult().get(0);
                return queryWarehouseInfo;
            }

            // 若 逻辑仓已传，需要通过Code转换ID处理
            WmsQueryWarehouseZoneListRequest byIdRequest = new WmsQueryWarehouseZoneListRequest();
            byIdRequest.setCode(shippingWarehouseCode);
            WmsQueryWarehouseZoneListResponse response = unifiedInventoryService.wmsQueryWarehouseZoneList(byIdRequest);
            log.info("OrderLineAtomUpdateRequestToOrderLineConvert#queryReceiveWarehouseInfo request:{}; response:{}", JSONObject.toJSONString(byIdRequest), JSONObject.toJSONString(response));
            if (Objects.nonNull(response) && CollectionUtils.isNotEmpty(response.getResult())) {
                WarehouseInfo queryWarehouseInfo = response.getResult().get(0);
                // (缓存) 逻辑仓库
                return queryWarehouseInfo;

            }
            throw new FunctionException("OC-01-001-01-16-009", String.format("逻辑仓编码:%s", shippingWarehouseCode));
        }
        return null;
    }

    /**
     * 将要修改的字段赋值给 更新对象
     * 如有其他字段要更新，在子类重新本方法
     */
    public boolean convert(OrderLine dbOrderLine, OrderLineAtomUpdateRequest orderLineRequest, String orderCategory) {
        log.info("OrderLineAtomUpdateRequestToOrderLineConvert#convert dbOrderLine:{}, orderLineRequest:{}",
                JSONObject.toJSONString(dbOrderLine), JSONObject.toJSONString(orderLineRequest));
        boolean hasInfoChange = false;
        JSONObject features = JSON.parseObject(Optional.ofNullable(dbOrderLine.getFeatures()).orElse(""));

        // 待提交/待推送状态下可修改字段
        if (OrderStatus.BEFORE_SUBMIT.getCode().equals(dbOrderLine.getStatus())
                || OrderStatus.STAY_PUSH.getCode().equals(dbOrderLine.getStatus())) {
            if (StringUtils.isNotBlank(orderLineRequest.getProductQuantity())) {
                dbOrderLine.setQuantity(Integer.parseInt(orderLineRequest.getProductQuantity()));
                hasInfoChange = true;
            }
            if (StringUtils.isNotBlank(orderLineRequest.getStockConversionNum())) {
                dbOrderLine.setStockConversionNum(orderLineRequest.getStockConversionNum());
                hasInfoChange = true;
            }
            if (StringUtils.isNotBlank(orderLineRequest.getSalesUnitCode())) {
                dbOrderLine.setSaleUnit(orderLineRequest.getSalesUnitCode());
                hasInfoChange = true;
            }
            if (StringUtils.isNotBlank(orderLineRequest.getSalesUnitName())) {
                dbOrderLine.setSaleUnitName(orderLineRequest.getSalesUnitName());
                hasInfoChange = true;
            }
            if (StringUtils.isNotBlank(orderLineRequest.getUnitConversionRelationship())) {
                dbOrderLine.setUnitConvert(orderLineRequest.getUnitConversionRelationship());
                hasInfoChange = true;
            }
            if (StringUtils.isNotBlank(orderLineRequest.getStockName())) {
                dbOrderLine.setStockName(orderLineRequest.getStockName());
                hasInfoChange = true;
            }
            if (StringUtils.isNotBlank(orderLineRequest.getDeliveryFactoryName())) {
                dbOrderLine.setDeliveryFactoryName(orderLineRequest.getDeliveryFactoryName());
                hasInfoChange = true;
            }
            if (StringUtils.isNotBlank(orderLineRequest.getStockCode())
                    || StringUtils.isNotBlank(orderLineRequest.getDeliveryFactoryCode())
                    || StringUtils.isNotBlank(orderLineRequest.getShippingWarehouseCode())
            ) {
                //有1个发货仓相关字段传值了，就可能是修改，就重新查出仓库进行赋值
                WarehouseInfo warehouseInfo = queryLgWarehouseInfo(orderLineRequest.getShippingWarehouseCode(),
                        orderLineRequest.getDeliveryFactoryCode(), orderLineRequest.getStockCode());
                dbOrderLine.setShippingWarehouseCode(warehouseInfo.getId());
                dbOrderLine.setShippingWarehouseOutCode(warehouseInfo.getCode());
                dbOrderLine.setShippingWarehouseName(warehouseInfo.getName());
                if (StringUtils.isNotBlank(warehouseInfo.getWarehouseCode())) {
                    dbOrderLine.setStockCode(warehouseInfo.getWarehouseCode());
                } else if (StringUtils.isNotBlank(orderLineRequest.getStockCode())) {
                    dbOrderLine.setStockCode(orderLineRequest.getStockCode());
                }
                dbOrderLine.setDeliveryFactoryCode(warehouseInfo.getSapFactoryCode());
                hasInfoChange = true;
            }
            //换货单回填收货仓信息
            if (dbOrderLine.getOrderLineTag().equals(SetOrderTag.EXCHANGE)) {
                if (StringUtils.isNotBlank(orderLineRequest.getReceiveStockCode())
                        || StringUtils.isNotBlank(orderLineRequest.getReceiveWarehouseCode())
                        || StringUtils.isNotBlank(orderLineRequest.getReceiveFactoryCode())
                ) {
                    //有1个收货仓相关字段传值了，就可能是修改，就重新查出仓库进行赋值
                    WarehouseInfo warehouseInfo = queryLgWarehouseInfo(orderLineRequest.getReceiveWarehouseCode(),
                            orderLineRequest.getReceiveFactoryCode(), orderLineRequest.getReceiveStockCode());
                    dbOrderLine.setReceiveWarehouseCode(warehouseInfo.getId());
                    dbOrderLine.setReceiveWarehouseOutCode(warehouseInfo.getCode());
                    dbOrderLine.setReceiveWarehouseName(warehouseInfo.getName());
                    dbOrderLine.setReceiveStockCode(warehouseInfo.getWarehouseCode());
                    dbOrderLine.setReceiveFactoryCode(warehouseInfo.getSapFactoryCode());
                    hasInfoChange = true;
                }
            }
            if (StringUtils.isNotBlank(orderLineRequest.getReceiveStockName())) {
                dbOrderLine.setReceiveStockName(orderLineRequest.getReceiveStockName());
                hasInfoChange = true;
            }
            if (StringUtils.isNotBlank(orderLineRequest.getReceiveFactoryName())) {
                dbOrderLine.setReceiveFactoryName(orderLineRequest.getReceiveFactoryName());
                hasInfoChange = true;
            }
            if (StringUtils.isNotBlank(orderLineRequest.getStockConversionNum())) {
                dbOrderLine.setStockConversionNum(orderLineRequest.getStockConversionNum());
                hasInfoChange = true;
            }
            if (StringUtils.isNotBlank(orderLineRequest.getSalesUnitCode())) {
                dbOrderLine.setSaleUnit(orderLineRequest.getSalesUnitCode());
                hasInfoChange = true;
            }
            if (StringUtils.isNotBlank(orderLineRequest.getSalesUnitName())) {
                dbOrderLine.setSaleUnitName(orderLineRequest.getSalesUnitName());
                hasInfoChange = true;
            }
            if (StringUtils.isNotBlank(orderLineRequest.getStockUnitCode())) {
                dbOrderLine.setInventoryUnitCode(orderLineRequest.getStockUnitCode());
                hasInfoChange = true;
            }
            if (StringUtils.isNotBlank(orderLineRequest.getStockUnitName())) {
                dbOrderLine.setInventoryUnit(orderLineRequest.getStockUnitName());
                hasInfoChange = true;
            }
            if (StringUtils.isNotBlank(orderLineRequest.getProductionDate())) {
                dbOrderLine.setProductationTime(DateUtils.parse(orderLineRequest.getProductionDate()));
                hasInfoChange = true;
            }
            if (StringUtils.isNotBlank(orderLineRequest.getBizFeatures())) {
                dbOrderLine.setBizFeatures(orderLineRequest.getBizFeatures());
                hasInfoChange = true;
            }
            if (StringUtils.isNotBlank(orderLineRequest.getUnitPrice())) {
                dbOrderLine.setUnitPrice(MoneyUtils.moneyStrYuan2Fen(orderLineRequest.getUnitPrice()));
                hasInfoChange = true;
            }
            if (StringUtils.isNotBlank(orderLineRequest.getTotalAmount())) {
                dbOrderLine.setShouldPayFee(MoneyUtils.moneyStrYuan2Fen(orderLineRequest.getTotalAmount()));
                hasInfoChange = true;
            }

            //如果新传入了总价或者数量，要重新算手工单价 总价 数量
            if (StringUtils.isNotBlank(orderLineRequest.getManualTotalAmount()) || StringUtils.isNotBlank(orderLineRequest.getProductQuantity())) {
                String totalAmount = MoneyUtils.moneyStrYuan2Fen(orderLineRequest.getManualTotalAmount());
                if (StringUtils.isBlank(totalAmount)) {
                    totalAmount = dbOrderLine.getManualTotalAmount();
                }
                Integer quantity = dbOrderLine.getQuantity();
                if (StringUtils.isNotBlank(orderLineRequest.getProductQuantity())) {
                    quantity = Integer.parseInt(orderLineRequest.getProductQuantity());
                }
                if (StringUtils.isNotBlank(totalAmount) && quantity > 0) {
                    BigDecimal manualPrice = new BigDecimal(totalAmount).divide(new BigDecimal(quantity), 0, RoundingMode.HALF_UP);
                    dbOrderLine.setQuantity(quantity);
                    dbOrderLine.setManualTotalAmount(totalAmount);
                    dbOrderLine.setManualPrice(manualPrice.toPlainString());
                    features.put(OrderFeaturesKey.MANUAL_PRICE, manualPrice.toPlainString());//手工单价
                    features.put(OrderFeaturesKey.MANUAL_TOTAL_AMOUNT, totalAmount);//手工总金额
                }
                hasInfoChange = true;
            }

            // 来单单位
            if (StringUtils.isNotBlank(orderLineRequest.getSourceUnit())) {
                features.put(OrderFeaturesKey.SOURCE_UNIT, orderLineRequest.getSourceUnit());
                hasInfoChange = true;
            }
            // 来单数量
            if (StringUtils.isNotBlank(orderLineRequest.getSourceQuantity())) {
                features.put(OrderFeaturesKey.SOURCE_QUANTITY, orderLineRequest.getSourceQuantity());
                hasInfoChange = true;
            }
            // 来单价格
            if (StringUtils.isNotBlank(orderLineRequest.getSourcePrice())) {
                features.put(OrderFeaturesKey.SOURCE_PRICE, orderLineRequest.getSourcePrice());
                hasInfoChange = true;
            }
            // 确认数量
            if (StringUtils.isNotBlank(orderLineRequest.getConfirmQuantity())) {
                dbOrderLine.setConfirmQuantity(Integer.parseInt(orderLineRequest.getConfirmQuantity()));
                hasInfoChange = true;
            }
            // 销售数量
            if (StringUtils.isNotBlank(orderLineRequest.getProductQuantity())) {
                dbOrderLine.setQuantity(Integer.parseInt(orderLineRequest.getProductQuantity()));
                hasInfoChange = true;
            }
            // 生产日期
            if (StringUtils.isNotBlank(orderLineRequest.getProductionDate())) {
                dbOrderLine.setProductationTime(DateUtils.parse(orderLineRequest.getProductionDate()));
                hasInfoChange = true;
            }
            // 发票号
            if (StringUtils.isNotBlank(orderLineRequest.getInvoiceNo())) {
                features.put(OrderFeaturesKey.INVOICE_NO, orderLineRequest.getInvoiceNo());
                hasInfoChange = true;
            }
            // 发票行号
            if (StringUtils.isNotBlank(orderLineRequest.getInvoiceLineNo())) {
                features.put(OrderFeaturesKey.INVOICE_LINE_NO, orderLineRequest.getInvoiceLineNo());
                hasInfoChange = true;
            }
        }

        // 待交货/部分交货状态下可修改字段
        if (OrderStatus.BEFORE_DELIVERY.getCode().equals(dbOrderLine.getStatus())
                || OrderStatus.PARTIAL_DELIVER.getCode().equals(dbOrderLine.getStatus())) {
            if (StringUtils.isNotBlank(orderLineRequest.getNote())) {
                dbOrderLine.setRemark(orderLineRequest.getNote());
                hasInfoChange = true;
            }
            // 确认数量
            if (StringUtils.isNotBlank(orderLineRequest.getConfirmQuantity())) {
                dbOrderLine.setConfirmQuantity(Integer.parseInt(orderLineRequest.getConfirmQuantity()));
                hasInfoChange = true;
            }
            // 来单单位
            if (StringUtils.isNotBlank(orderLineRequest.getSourceUnit())) {
                features.put(OrderFeaturesKey.SOURCE_UNIT, orderLineRequest.getSourceUnit());
                hasInfoChange = true;
            }
            // 来单数量
            if (StringUtils.isNotBlank(orderLineRequest.getSourceQuantity())) {
                features.put(OrderFeaturesKey.SOURCE_QUANTITY, orderLineRequest.getSourceQuantity());
                hasInfoChange = true;
            }
            // 来单价格
            if (StringUtils.isNotBlank(orderLineRequest.getSourcePrice())) {
                features.put(OrderFeaturesKey.SOURCE_PRICE, orderLineRequest.getSourcePrice());
                hasInfoChange = true;
            }
            // 生产日期
            if (StringUtils.isNotBlank(orderLineRequest.getProductionDate())) {
                dbOrderLine.setProductationTime(DateUtils.parse(orderLineRequest.getProductionDate()));
                hasInfoChange = true;
            }
        }

        // 所有状态都可修改字段
        if (OrderCategoryEnum.COMPANY.equals(OrderCategoryEnum.of(orderCategory))) {
            dbOrderLine.setRemark(orderLineRequest.getNote());
            hasInfoChange = true;
        } else {
            if (StringUtils.isNotBlank(orderLineRequest.getNote())) {
                dbOrderLine.setRemark(orderLineRequest.getNote());
                hasInfoChange = true;
            }
        }

        // 其他
        dbOrderLine.setFeatures(features.toJSONString());

        return hasInfoChange;
    }

    public boolean convertNew(OrderLine dbOrderLine, OrderLineAtomUpdateRequest orderLineRequest) {
        boolean hasInfoChange = false;
        JSONObject features = JSON.parseObject(Optional.ofNullable(dbOrderLine.getFeatures()).orElse(""));

        if (StringUtils.isNotBlank(orderLineRequest.getStockCode())
                || StringUtils.isNotBlank(orderLineRequest.getDeliveryFactoryCode())
                || StringUtils.isNotBlank(orderLineRequest.getShippingWarehouseCode())
        ) {
            WarehouseInfo warehouseInfo = queryLgWarehouseInfo(orderLineRequest.getShippingWarehouseCode(),
                    orderLineRequest.getDeliveryFactoryCode(), orderLineRequest.getStockCode());
            dbOrderLine.setShippingWarehouseCode(warehouseInfo.getId());
            dbOrderLine.setShippingWarehouseOutCode(warehouseInfo.getCode());
            dbOrderLine.setShippingWarehouseName(warehouseInfo.getName());
            if (StringUtils.isNotBlank(warehouseInfo.getWarehouseCode())) {
                dbOrderLine.setStockCode(warehouseInfo.getWarehouseCode());
            } else if (StringUtils.isNotBlank(orderLineRequest.getStockCode())) {
                dbOrderLine.setStockCode(orderLineRequest.getStockCode());
            }
            dbOrderLine.setDeliveryFactoryCode(warehouseInfo.getSapFactoryCode());
            hasInfoChange = true;
        }

        // 确认数量
        if (StringUtils.isNotBlank(orderLineRequest.getConfirmQuantity())) {
            dbOrderLine.setConfirmQuantity(Integer.parseInt(orderLineRequest.getConfirmQuantity()));
            hasInfoChange = true;
        }
        // 来单单位
        if (StringUtils.isNotBlank(orderLineRequest.getSourceUnit())) {
            features.put(OrderFeaturesKey.SOURCE_UNIT, orderLineRequest.getSourceUnit());
            hasInfoChange = true;
        }
        // 来单数量
        if (StringUtils.isNotBlank(orderLineRequest.getSourceQuantity())) {
            features.put(OrderFeaturesKey.SOURCE_QUANTITY, orderLineRequest.getSourceQuantity());
            hasInfoChange = true;
        }
        // 来单价格
        if (StringUtils.isNotBlank(orderLineRequest.getSourcePrice())) {
            features.put(OrderFeaturesKey.SOURCE_PRICE, orderLineRequest.getSourcePrice());
            hasInfoChange = true;
        }

        // 生产日期
        if (StringUtils.isNotBlank(orderLineRequest.getProductionDate())) {
            dbOrderLine.setProductationTime(DateUtils.parse(orderLineRequest.getProductionDate()));
            hasInfoChange = true;
        }

        String modifyQuantity = orderLineRequest.getProductQuantity();
        Integer dbQuantity = dbOrderLine.getQuantity();
        if (StringUtils.isNotBlank(modifyQuantity)) {
            int modifyQuantityInt = Integer.valueOf(modifyQuantity);
            dbOrderLine.setQuantity(modifyQuantityInt);
            if (StringUtils.isNotBlank(dbOrderLine.getUnitConvert()) && Objects.nonNull(dbOrderLine.getQuantity())) {
                dbOrderLine.setStockConversionNum(new BigDecimal(dbOrderLine.getQuantity()).divide(new BigDecimal(dbOrderLine.getUnitConvert()), 2, RoundingMode.HALF_UP).toString());
            }
            if (dbQuantity != modifyQuantityInt) {
                dbOrderLine.setCumulativeNoticeQuantity("0");
                features.put(OrderFeaturesKey.FULFILLMENT_STATUS, FulfillmentStatusEnum.BEFORE_FULFILLMENT.getCode());
            }
            hasInfoChange = true;
        }
        if (StringUtils.isNotBlank(orderLineRequest.getSalesUnitCode())) {
            dbOrderLine.setSaleUnit(orderLineRequest.getSalesUnitCode());
            dbOrderLine.setSaleUnitName(orderLineRequest.getSalesUnitName());
            hasInfoChange = true;
        }
        if (StringUtils.isNotBlank(orderLineRequest.getSalesUnitCode())) {
            dbOrderLine.setSaleUnit(orderLineRequest.getSalesUnitCode());
            dbOrderLine.setSaleUnitName(orderLineRequest.getSalesUnitName());
            hasInfoChange = true;
        }
        if (StringUtils.isNotBlank(orderLineRequest.getNote())) {
            dbOrderLine.setRemark(orderLineRequest.getNote());
            hasInfoChange = true;
        }
        String bizFeatures = orderLineRequest.getBizFeatures();
        if (StringUtils.isNotBlank(bizFeatures)) {
            /* JSONObject bizFeaturesJson = JSONObject.parseObject(bizFeatures);
            String fulfillmentMsg = (String) bizFeaturesJson.get(OrderFeaturesKey.FULFILLMENT_MSG);
            if (StringUtils.isNotBlank(fulfillmentMsg)) {
                features.put(OrderFeaturesKey.FULFILLMENT_MSG, fulfillmentMsg);
            } */
            dbOrderLine.setBizFeatures(bizFeatures);
            hasInfoChange = true;
        }
        dbOrderLine.setFeatures(features.toJSONString());
        return hasInfoChange;
    }

    public WarehouseInfo queryLgWarehouseInfo(String warehouseCode, String factoryCode, String stockCode) {
        if (StringUtils.isBlank(warehouseCode)) {
            // 当逻辑仓库信息为空时，通过 交货工厂编码+交货库存地点 填充
            SpecQueryWarehouseRequest cargoRequest = new SpecQueryWarehouseRequest();
            cargoRequest.setFactoryCode(factoryCode);
            cargoRequest.setInventoryCode(stockCode);
            cargoRequest.setModel(3);
            //销售单元仓 TODO 3.6 啥意思
            cargoRequest.setTypeList(Lists.newArrayList(3, 6));
            Result<List<WarehouseInfo>> cargoResponse = bcOrderService.specQueryWarehouse(cargoRequest);

            if (Objects.isNull(cargoResponse) || CollectionUtils.isEmpty(cargoResponse.getResult())) {
                throw new FunctionException("OC-01-001-01-16-009", String.format("!工厂编码:%s, 库存地点编码:%s",
                        factoryCode,
                        stockCode));
            }
            WarehouseInfo queryWarehouseInfo = cargoResponse.getResult().get(0);
            return queryWarehouseInfo;
        }

        // 若 逻辑仓已传，需要通过Code转换ID处理
        WarehouseInfo warehouseInfo = cargoZoneAdapter.searchCargoZone(warehouseCode);
        if (Objects.isNull(warehouseInfo)) {
            throw new FunctionException("OC-01-001-01-16-010", String.format("逻辑仓编码:%s", warehouseCode));
        }
        return warehouseInfo;
    }

}
